/*
 * MAtoms.h
 *
 *  Created on: Aug 7, 2013
 *      Author: marchi
 */

#ifndef MATOMS_H_
#define MATOMS_H_


#include <string>
#include <map>
#include <algorithm>
#include <cmath>
#include <array>
#include <iterator>
#include <cmath>

#include "FAtoms.h"
#include "TopolMic.h"
#include "MyUtilClass.h"
#include "Gyration.h"
#include "CenterMass.h"
#include "CenterMassBW.h"
#include "CenterMassBW2.h"
#include "CenterMassBW3.h"
#include "Percolation.h"
#include "linalg.h"
#include "Quaternions.hpp"
#include "WignerDMatrices.hpp"

using namespace std;
using namespace Topol_NS;
using namespace MATRIX;
using namespace DVECT;
using vectorvd=vector<vector<Dvect> >;
using vvvector_dv=vector<vector<vector<Dvect> > >;
using vectorvi=vector<vector<int> >;
using Quaternions::Quaternion;
using SphericalFunctions::WignerDMatrix;

class MAtoms: public FAtoms {
protected:
	map<string,vector<Dvect> > ResXYZ;
	static int calls;
	static vector<string> * ResList0;
	static vector<int> * ResIndx0;
	vector<Gyration> Rg_i,Rg_stat;
	CenterMass * R_cmx;
	vector<vector<Dvect> > Xref;
	int Rg_count;
	vector<double> mass, massNCH;
	static map<string,double> MMass;
	static map<string,double> MMassNCH;
	vector<string> atres;
	vector<string> atname;
	static string MIons;
	static string Mdetg;
	vector<vector<int> > MyRes,SelRes;
	vector<PDBdata> PDB;
	virtual void cPrint(ostream &);
	virtual void fPrint(Fstream &);
	Percolation * Perco;
	vector<vector<int> > Ovec;
	int iCountRot;
	void CalcGyro(vector<double> &,vector<Gyration> &);
	class RelativeCoord;
	vector<Dvect> CM_c0,CM_c1;
	vectorvd CM_m0,CM_m1;
public:
	MAtoms();
	MAtoms(int);
	MAtoms(Atoms & x): FAtoms(x),Rg_count(0), Perco(NULL), iCountRot{0}, R_cmx{new CenterMass} {};
 	MAtoms(Atoms & x, bool outisbinary): FAtoms(x),Rg_count(0), Perco(NULL), iCountRot{0} {
		if(outisbinary) R_cmx=new CenterMassBW;
		else R_cmx=new CenterMass;
	};
	void Reconstruct(const string &, TopolMic &);
	void Reconstruct();
	void InitSelection(vector<string> &, TopolMic &);
	void Gyro();
	void CompCM();
	void CompRot();
	Matrix InertiaRot();
	Dvect CM();
	Matrix InertiaRotCenter();
	Dvect CMCenter();

	virtual void initLists(TopolPDB &,vector<string> &);
	vector<Gyration> & getRg_i(){return Rg_i;};
	CenterMass & getCM(){return *R_cmx;}

	vector<double> getM(){return mass;}
	bool testMass(){return !mass.empty();}
	vector<int> & getIndx(){return *ResIndx0;}
	void Percolate(vector<vector<int> > &);
	Percolation & Percolate();
	Percolation & Percolate(double y){
		Perco->setRcut(y);
		return this->Percolate();
	}
	vector<Comp> & getComp(){return Perco->getClustComp();}
	virtual void gDipole(){};
	virtual void dPrint(ostream & fout){};
	static vector<string> & gResList(){return *ResList0;}
	static string gTotResList();
	friend ostream & operator<<(ostream & , MAtoms &);
	friend Fstream & operator<<(Fstream & fout, MAtoms &);
	virtual ~MAtoms();
};
class MAtoms::RelativeCoord{
	vector<Dvect> CM_c;
	vectorvd CM_m;
	vvvector_dv x_m;
public:
	RelativeCoord(MAtoms *,vectorvi &, vectorvi &);
	RelativeCoord(MAtoms *,vectorvi &, vectorvi &, string );
	vector<Dvect> getCM_c(){return CM_c;};
	vectorvd getCM_m(){return CM_m;};
};

#endif /* MATOMS_H_ */
